package com.planw.beetl.sql.search;

import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.psi.*;
import com.intellij.util.Processor;
import com.planw.beetl.utils.JavaService;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BeetlSqlJavaMapperQueryExecutorBase extends QueryExecutorBase<PsiElement, PsiElement> {

    public static void toSearchSqlByClass(PsiClass psiClass, Processor<? super PsiElement> consumer) {
        JavaService javaService = JavaService.getInstance(psiClass.getProject());
        if (!javaService.checkIsBeetlSqlClass(psiClass)) {
            return;
        }
        List<PsiFile> fileList = javaService.getAllBeetlSqlFiles(psiClass.getProject(), psiClass);
        if (fileList == null || fileList.isEmpty()) {
            return;
        }
        for (PsiFile psiElement : fileList) {
            consumer.process(psiElement);
        }
    }


    public static void toSearchSql(PsiMethod psiMethod, Processor<? super PsiElement> consumer) {
        PsiClass psiClass = psiMethod.getContainingClass();
        JavaService javaService = JavaService.getInstance(psiClass.getProject());
        if (!javaService.checkIsBeetlSqlClass(psiClass)) {
            return;
        }
        Map<String, PsiMethod> psiMethodMap = new HashMap<>();
        psiMethodMap.put(psiMethod.getName(), psiMethod);

        List<PsiFile> fileList = javaService.getAllBeetlSqlFiles(psiClass.getProject(), psiClass);
        if (fileList == null || fileList.isEmpty()) {
            return;
        }
        Map<String, List<PsiElement>> targetSqlElement = javaService.buildTargetPsiElement(fileList, psiMethodMap);
        if (targetSqlElement == null || targetSqlElement.isEmpty()) {
            return;
        }
        List<PsiElement> psiElements = targetSqlElement.get(psiMethod.getName());
        if (psiElements == null || psiElements.isEmpty()) {
            return;
        }
        for (PsiElement psiElement : psiElements) {
            consumer.process(psiElement);
        }

    }

    @Override
    public void processQuery(@NotNull PsiElement queryParameters, @NotNull Processor<? super PsiElement> consumer) {
        if (!(queryParameters instanceof PsiTypeParameterListOwner)) return;
        if (queryParameters instanceof PsiMethod) {
            PsiMethod psiMethod = (PsiMethod) queryParameters;
            if (ApplicationManager.getApplication().isReadAccessAllowed()) {
                toSearchSql(psiMethod, consumer);
            } else {
                ApplicationManager.getApplication().runReadAction(new Runnable() {
                    @Override
                    public void run() {
                        toSearchSql(psiMethod, consumer);
                    }
                });
            }
            return;
        }
    }
}
